package com.xz.repertory.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import com.alibaba.fastjson.JSON;
import com.xz.common.annotation.DataScope;
import com.xz.common.core.domain.AjaxResult;
import com.xz.common.domain.SysAccessory;
import com.xz.common.utils.DateUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xz.common.utils.SecurityUtils;
import com.xz.log.domain.OperationLog;
import com.xz.log.service.IOperationLogService;
import com.xz.purchase.domain.Purchase;
import com.xz.purchase.domain.PurchaseProduct;
import com.xz.purchase.service.IPurchaseProductService;
import com.xz.repertory.dto.RepertoryFlowBillDto;
import com.xz.repertory.dto.RepertoryFlowDto;
import common.ECDateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xz.repertory.mapper.RepertoryFlowMapper;
import com.xz.repertory.domain.RepertoryFlow;
import com.xz.repertory.service.IRepertoryFlowService;
import org.springframework.util.CollectionUtils;

/**
 * 库存流水Service业务层处理
 *
 * @author xz
 * @date 2024-01-06
 */
@Service
public class RepertoryFlowServiceImpl extends ServiceImpl<RepertoryFlowMapper, RepertoryFlow> implements IRepertoryFlowService {
    @Autowired
    private RepertoryFlowMapper repertoryFlowMapper;
    @Autowired
    private IOperationLogService operationLogService;
    @Autowired
    private IPurchaseProductService iPurchaseProductService;
    /**
     * 查询库存流水
     *
     * @param id 库存流水主键
     * @return 库存流水
     */
    @Override
    public RepertoryFlow selectRepertoryFlowById(Long id) {
        return repertoryFlowMapper.selectRepertoryFlowById(id);
    }

    /**
     * 查询库存流水列表--库存
     *
     * @param repertoryFlow 库存流水
     * @return 库存流水
     */
    @DataScope(deptAlias = "d", userAlias = "u")
    @Override
    public List<RepertoryFlowDto> selectRepertoryFlowList(RepertoryFlow repertoryFlow) {
        List<RepertoryFlowDto> repertoryFlowDtoList = repertoryFlowMapper.selectRepertoryFlowList(repertoryFlow);
        repertoryFlowDtoList.stream().forEach(i->{
            if(i.getFlowType()==1){
                i.setStorage(i.getQuantity());
                i.setPrice(null);
                i.setAmount(null);
                i.setDiscount(null);
            }else{
                i.setDeliveryStorage(i.getQuantity());
            }
        });
        return repertoryFlowDtoList;
    }
    /**
     * 查询库存流水列表--财务
     *
     * @param repertoryFlow 库存流水
     * @return 库存流水
     */
    @DataScope(deptAlias = "d", userAlias = "u")
    @Override
    public List<RepertoryFlowBillDto> selectRepertoryFlowBillList(RepertoryFlow repertoryFlow) {
        List<RepertoryFlowBillDto> repertoryFlowDtoList = repertoryFlowMapper.selectRepertoryFlowBillList(repertoryFlow);
        repertoryFlowDtoList.stream().forEach(i->{
            if(i.getFlowType()==1){
                i.setStorage(i.getQuantity());
            }else{
                i.setDeliveryStorage(i.getQuantity());
            }
        });
        return repertoryFlowDtoList;
    }

    @Override
    public List<PurchaseProduct> selectListByRepertoryFlow(RepertoryFlow repertoryFlow) {
        return repertoryFlowMapper.selectListByRepertoryFlow(repertoryFlow);
    }

    /**
     * 新增库存流水
     *
     * @param repertoryFlow 库存流水
     * @return 结果
     */
    @Override
    public int insertRepertoryFlow(RepertoryFlow repertoryFlow) {
        repertoryFlow.setCreateTime(DateUtils.getNowDate());
        return repertoryFlowMapper.insertRepertoryFlow(repertoryFlow);
    }

    /**
     * 修改库存流水
     *
     * @param repertoryFlow 库存流水
     * @return 结果
     */
    @Override
    public AjaxResult updateRepertoryFlow(RepertoryFlow repertoryFlow) {
        if(repertoryFlow.getId()==null){
            return AjaxResult.error("参数id不能为空");
        }
        RepertoryFlow flow = repertoryFlowMapper.selectRepertoryFlowById(repertoryFlow.getId());
        if(Objects.isNull(flow)){
            return AjaxResult.error("修改单价失败");
        }
        repertoryFlow.setUpdateTime(DateUtils.getNowDate());
        repertoryFlow.setUpdateBy(SecurityUtils.getUserId());
        //repertoryFlow.setCostAmount(repertoryFlow.getCostPrice().multiply(BigDecimal.valueOf(flow.getQuantity())));
        int updateRepertoryFlow = repertoryFlowMapper.updateRepertoryFlow(repertoryFlow);
        //修改入库商品单价
        flow.setCostPrice(repertoryFlow.getCostPrice());
        if((flow.getStorageType()==1 || flow.getStorageType()==8) && flow.getPurchaseProductId()!=null){
            iPurchaseProductService.updateCostPrice(flow);
        }
        if(updateRepertoryFlow>0){
            operationLogService.insertOperationLog(
                    new OperationLog(repertoryFlow.getId()+"",1,repertoryFlow.getTenantId(),
                            SecurityUtils.getUserId(),SecurityUtils.getUsername(), ECDateUtils.formatDate(new Date(),"yyyy-MM-dd") +"，修改，采购单价"+repertoryFlow.getCostPrice()+"元"));
        }
        return AjaxResult.success("修改单价成功");
    }

    /**
     * 批量删除库存流水
     *
     * @param ids 需要删除的库存流水主键
     * @return 结果
     */
    @Override
    public int deleteRepertoryFlowByIds(Long[] ids) {
        return repertoryFlowMapper.deleteRepertoryFlowByIds(ids);
    }

    /**
     * 删除库存流水信息
     *
     * @param id 库存流水主键
     * @return 结果
     */
    @Override
    public int deleteRepertoryFlowById(Long id) {
        return repertoryFlowMapper.deleteRepertoryFlowById(id);
    }

    /**
     * 处理流水数据
     * @param purchaseProduct 数据
     * @param type 型（1.入库 2.出库）
     * @param storageType 出入库类型(
     *                      1.采购入库 2.采购入库（冲红） 3.采购退货 4.采购退货（冲红）5.库存调拨（出）6.库存调拨（入）7.库存调整出库 8.库存调整入库
     *                      9.库存报损 10.销售出库 11.库存调整入库（冲红）12.取消销售单且商品入库 13.销售单退货入库 14.销售单换货入库 15.销售单换货出库
     *                      16.贸易中间商发货单（发货） 17.贸易中间商发货单（冲红） 18.贸易中间商退货单（退货） 19.贸易中间商退货单（冲红）
     *                      20.贸易中间商换货单（退货） 21.贸易中间商换货单（换货） 22.贸易中间商换货单（退货冲红） 23.贸易中间商换货单（换货冲红） 24.诊疗领药
     *                    )
     * @return
     */
    @Override
    public RepertoryFlow dataRepertoryFlow(PurchaseProduct purchaseProduct,Integer type,Integer storageType) {
        RepertoryFlow repertoryFlow=new RepertoryFlow();
        repertoryFlow.setFlowType(type);
        repertoryFlow.setStorageType(storageType);
        saveRepertoryFlow(repertoryFlow,purchaseProduct);
        return repertoryFlow;
    }

    /**
     * 处理流水数据
     * @param repertoryFlow
     * @param purchase
     */
    public void saveRepertoryFlow(RepertoryFlow repertoryFlow,PurchaseProduct purchase){
        repertoryFlow.setNumber(purchase.getPurchaseNumber());
        if(new Integer(8).equals(repertoryFlow.getStorageType())){
            repertoryFlow.setNumber(purchase.getOtherPurchaseNumber());
        }
        repertoryFlow.setWarehouseName(purchase.getWarehouseName());
        repertoryFlow.setMemberId(purchase.getMemberId());
        repertoryFlow.setMemberName(purchase.getMemberName());

        repertoryFlow.setProductName(purchase.getProductName());
        repertoryFlow.setProductParameter(purchase.getProductParam());
        repertoryFlow.setBatchNumber(purchase.getBatchNumber());
        repertoryFlow.setValidity(purchase.getValidity());
        // 出入库类型(1.采购入库 2.采购入库（冲红） 3.采购退货
        // 4.采购退货（冲红）5.库存调拨（出）6.库存调拨（入）7.库存调整出库
        // 8.库存调整入库 9.库存报损 10.销售出库 11.库存调整入库（冲红）
        // 12.取消销售单商品入库)  13.销售单退货入库 14.销售单换货入库 15.销售单换货出库
        // 16.贸易中间商发货单（发货） 17.贸易中间商发货单（冲红） 18.贸易中间商退货单（退货） 19.贸易中间商退货单（冲红）
       //  20.贸易中间商换货单（退货） 21.贸易中间商换货单（换货） 22.贸易中间商换货单（退货冲红） 23.贸易中间商换货单（换货冲红） 24.诊疗领药
        if(repertoryFlow.getStorageType()==2 || repertoryFlow.getStorageType()==4  || repertoryFlow.getStorageType()==11
          || repertoryFlow.getStorageType()==17 || repertoryFlow.getStorageType()==19
          || repertoryFlow.getStorageType()==22 || repertoryFlow.getStorageType()==24){
            repertoryFlow.setQuantity(-purchase.getInventoryQuantity());
        }else{
            repertoryFlow.setQuantity(purchase.getInventoryQuantity());
        }
        repertoryFlow.setTenantId(purchase.getTenantId());
        repertoryFlow.setDeptId(purchase.getDeptId());
        repertoryFlow.setProductId(purchase.getProductId());
        repertoryFlow.setCostPrice(purchase.getCostPrice());
        repertoryFlow.setPrice(purchase.getCostPrice());
        repertoryFlow.setRemark(purchase.getRemark());
        if(purchase.getCostPrice()!=null&&purchase.getStorageNum()!=null){
            repertoryFlow.setCostAmount(purchase.getCostPrice().multiply(BigDecimal.valueOf(purchase.getStorageNum())));
        }
        if(repertoryFlow.getStorageType()==10 || repertoryFlow.getStorageType()==13 ||  repertoryFlow.getStorageType()==14 ||  repertoryFlow.getStorageType()==15 ){
            repertoryFlow.setCostAmount(purchase.getCostPrice().multiply(BigDecimal.valueOf(purchase.getInventoryQuantity())));
            if(repertoryFlow.getStorageType()==10 || repertoryFlow.getStorageType()==15){
                repertoryFlow.setPrice(purchase.getPrice());
                repertoryFlow.setAmount(purchase.getSubtotal());
                BigDecimal price = purchase.getPrice();
                Integer inventoryQuantity = purchase.getInventoryQuantity();
                BigDecimal multiply = price.multiply(BigDecimal.valueOf(inventoryQuantity));
                BigDecimal subtract = multiply.subtract(purchase.getSubtotal());
                repertoryFlow.setDiscount(subtract);
            }
            if(repertoryFlow.getStorageType()==13 ){
                repertoryFlow.setAmount(BigDecimal.ZERO.subtract(purchase.getSubtotal()));
                repertoryFlow.setPrice(purchase.getPrice());
                BigDecimal price = purchase.getPrice();
                Integer inventoryQuantity = purchase.getInventoryQuantity();
                inventoryQuantity = 0-inventoryQuantity;
                BigDecimal multiply = price.multiply(BigDecimal.valueOf(inventoryQuantity));
                BigDecimal subtract = multiply.subtract(repertoryFlow.getAmount());
                repertoryFlow.setDiscount(subtract);
            }
            if(repertoryFlow.getStorageType()==14 ){
                repertoryFlow.setPrice(purchase.getPrice());
                repertoryFlow.setAmount(BigDecimal.ZERO);   //换货入库的实收金额为0
                repertoryFlow.setDiscount(BigDecimal.ZERO); //换货入库的优惠金额为0
            }
        }else if(repertoryFlow.getStorageType() >= 16 && repertoryFlow.getStorageType() <= 23){
          // 贸易中间商（流水类型在16~23间）的出入库流水，其金额相关字段与其他模块的单据不一样，需要单独处理。
          // 成本单价
          repertoryFlow.setCostPrice(purchase.getCostPrice());
          // 成本金额 = 成本单价*数量
          repertoryFlow.setCostAmount(purchase.getCostPrice().multiply(BigDecimal.valueOf(purchase.getInventoryQuantity())));
          // 合同单价
          repertoryFlow.setPrice(purchase.getPrice());
          // 金额 = 合同单价 * 数量
          repertoryFlow.setAmount(purchase.getPrice().multiply(BigDecimal.valueOf(repertoryFlow.getQuantity())));
          // 优惠价 = 成本单价*数量-合同单价*数量
          if(repertoryFlow.getQuantity() >= 0){
            repertoryFlow.setDiscount(repertoryFlow.getCostAmount().subtract(repertoryFlow.getAmount()));
          }
        }
        repertoryFlow.setProductEncoded(purchase.getProductEncoded());
        repertoryFlow.setDeptId(purchase.getDeptId());
        repertoryFlow.setCreateBy(purchase.getCreateBy());
        if(Objects.isNull(purchase.getCreateTime())){
            repertoryFlow.setCreateTime(new Date());
        }else{
            repertoryFlow.setCreateTime(purchase.getCreateTime());
        }
        repertoryFlow.setPurchaseProductId(purchase.getId());
        repertoryFlow.setBusinessId(purchase.getBusinessId());
        repertoryFlow.setPurchaseProductId(purchase.getId());
        repertoryFlow.setSupplierId(purchase.getSupplierId());
        repertoryFlow.setSupplierName(purchase.getSupplierName());

    }

    @Override
    public boolean saveRepertoryFlowList(List<PurchaseProduct> list, Integer type, Integer storageType) {
        list.stream().forEach(i->{
            RepertoryFlow flow = dataRepertoryFlow(i, type, storageType);
            this.save(flow);
            BigDecimal costPrice = i.getCostPrice()==null?BigDecimal.ZERO:i.getCostPrice();
            operationLogService.insertOperationLog(
                        new OperationLog(flow.getId()+"",1,i.getTenantId(),
                                SecurityUtils.getUserId(),SecurityUtils.getUsername(), ECDateUtils.formatDate(new Date(),"yyyy-MM-dd") +"，创建，采购单价"+costPrice+"元"));
        });
        return false;
    }

    @Override
    public boolean saveRepertoryFlow(List<PurchaseProduct> list, Integer type, Integer storageType) {
        List<RepertoryFlow> repertoryFlow =new ArrayList<>();
        list.stream().forEach(i->{
            repertoryFlow.add(dataRepertoryFlow(i, type,storageType));
        });
        if(!CollectionUtils.isEmpty(repertoryFlow)){
            return this.saveBatch(repertoryFlow);
        }
        return false;
    }

    @Override
    public List<PurchaseProduct> convertFlowData(List<PurchaseProduct> list,Integer operateNumber,String purchaseNumber,Long businessId){
        List<PurchaseProduct> convertList = new ArrayList<>();
        for (PurchaseProduct purchaseProduct:list) {
            Integer availableStock = purchaseProduct.getAvailableStock();
            operateNumber -= availableStock;
            purchaseProduct.setRemark(purchaseProduct.getRemark());
            purchaseProduct.setPurchaseNumber(purchaseNumber);
            purchaseProduct.setBusinessId(businessId);
            if(operateNumber>0){
                purchaseProduct.setInventoryQuantity(availableStock);
                purchaseProduct.setAvailableStock(0);
                convertList.add(purchaseProduct);
                iPurchaseProductService.updateById(purchaseProduct);
                continue;
            }else{
                purchaseProduct.setInventoryQuantity(availableStock+operateNumber);
                purchaseProduct.setAvailableStock(0-operateNumber);
                convertList.add(purchaseProduct);
                iPurchaseProductService.updateById(purchaseProduct);
                break;
            }
        }
        return convertList;
    }
}
